home *** CD-ROM | disk | FTP | other *** search
- //==============================================================================
- // Scn10p2: AI Scenario Script for scenario 10 player 2
- //==============================================================================
- /*
- AI owner: Mike Kidd
- Scenario owner: Jeff Brown
-
- Overview:
- The player needs to rescue Chiron, but must achieve a number of
- intermediate objectives. First, he picks up a bunch of centaurs, then uses
- them to kill prison guards to claim one area and get resources. The player
- makes a few more units, then goes to capture first one part, then another, of
- the city. Finally, the player can use siege to destroy the bandits' migdol
- fortress.
-
- The AI has a few components. A simple economic framework will keep villagers
- gathering in several zones of the map. Triggers will spawn units and call a
- spawn() AI function, with parameters indicating that it should attack P1 units,
- P1 buildings, or P8 (P1 ally) buildings using a pair of attack routes.
-
- Finally, when the player is about to start his assault on the fortress, the
- CPAI will spawn one last set of defenders, which will be absorbed into a defend plan.
-
- The CPAI does no unit training and no upgrading, and very limited god power usage.
-
- Difficulty is adjusted through the size and timing of spawned unit groups.
-
- 7/31/2002: Added economic AI bits to keep gatherers busy.
-
- */
- //==============================================================================
-
-
- include "scn lib.xs";
-
- // Globals
- int lastAttackPlanID = -1; // Updated with plan ID as each attack is launched
-
- int startTime = -1; // Updated with start time when cinematic is done. In seconds.
- int visionTime = -1; // Updated by wakeup() function, time (in sec) to cast vision.
- int age3Time = 720; // OK to go to age 3 at 12 minutes
- int age4Time = 1500; // OK to go to age 4 at 25 minutes
- int nextAttackTime = 300;
- int attackInterval = 180;
- int nextAttackSize = 3;
- int attackSizeIncrement = 1;
-
- int siegeMaintainPlan = -1;
- int mythMaintainPlan = -1;
- int barracksUnitMaintainPlan = -1;
- int barracksUnit = -1;
- int chariotMaintainPlan = -1;
-
- int attackQuery = -1; // Shared by all armies
- int attackQuery2 = -1; // Additional query for building targets
- int attackQuery3 = -1; // Additional query for player 3 buildings
-
- int gathererTypeID = -1;
- int mainBase = -1; // Used for gathering, centered north of TC
- int woodBase = -1; // Used for wood only, west of TC, centered on lumber camp.
-
-
- // Cinematic block markers
-
- const string cbRouteInnerA = "6438";
- const string cbRouteInnerB = "6439";
- const string cbRouteInnerC = "6440";
-
- const string cbRouteOuterA = "6441";
- const string cbRouteOuterB = "6442";
- const string cbRouteOuterC = "6443";
-
- const string cbTownCenter = "6444";
- const string cbBase2 = "6450";
-
-
-
-
- int routeInner = -1;
- int routeOuter = -1;
-
-
- // *****************************************************************************
- //
- // FUNCTIONS
- //
- // *****************************************************************************
-
-
- int initMainBase(vector center=vector(-1,-1,-1), float radius = 50.0)
- {
- int baseID = -1;
- // Nuke bases, add one base to rule them all
- kbBaseDestroyAll(cMyID);
-
- baseID = kbBaseCreate(cMyID, "Base "+kbBaseGetNextID(), center, radius);
- if (baseID < 0)
- aiEcho("***** Main base creation failed. *****");
-
- vector baseFront=xsVectorNormalize(kbGetMapCenter()-center); // Set front
- kbBaseSetFrontVector(cMyID, mainBase, baseFront);
- kbBaseSetMaximumResourceDistance(cMyID, baseID, radius+20.0); // Gather up to 20m beyond base perimeter
- kbBaseSetMain(cMyID, baseID, true); // Make this the main base
-
- // Add the buildings
- int buildingQuery = -1;
- int count = 0;
- buildingQuery = kbUnitQueryCreate("Building Query"); // All buildings in the base
- configQuery(buildingQuery, cUnitTypeBuilding, -1, cUnitStateAliveOrBuilding, cMyID, center, false, radius);
- kbUnitQueryResetResults(buildingQuery);
- count = kbUnitQueryExecute(buildingQuery);
-
- int i = 0;
- int buildingID = -1;
- for (i=0; < count)
- {
- buildingID = kbUnitQueryGetResult(buildingQuery, i);
- // Add it to the base
- kbBaseAddUnit( cMyID, baseID, buildingID );
- }
- return(baseID);
- }
-
-
-
- int makeBase(vector center=vector(-1,-1,-1), float radius = 50.0)
- {
- int baseID = -1;
-
- baseID = kbBaseCreate(cMyID, "Base "+kbBaseGetNextID(), center, radius);
- if (baseID < 0)
- aiEcho("***** Base creation failed. *****");
-
- vector baseFront=xsVectorNormalize(kbGetMapCenter()-center); // Set front
- kbBaseSetFrontVector(cMyID, mainBase, baseFront);
- kbBaseSetMaximumResourceDistance(cMyID, baseID, radius+20.0); // Gather up to 20m beyond base perimeter
-
- // Add the buildings
- int buildingQuery = -1;
- int count = 0;
- buildingQuery = kbUnitQueryCreate("Base Query"); // All buildings in the base
- configQuery(buildingQuery, cUnitTypeBuilding, -1, cUnitStateAliveOrBuilding, cMyID, center, false, radius);
- kbUnitQueryResetResults(buildingQuery);
- count = kbUnitQueryExecute(buildingQuery);
-
- int i = 0;
- int buildingID = -1;
- for (i=0; < count)
- {
- buildingID = kbUnitQueryGetResult(buildingQuery, i);
- // Add it to the base
- kbBaseAddUnit( cMyID, baseID, buildingID );
- }
- return(baseID);
- }
-
-
- void initEcon()
- {
- aiSetAttackResponseDistance(20.0); // Kill escrows
- kbEscrowSetPercentage( cEconomyEscrowID, cAllResources, 0.0);
- kbEscrowSetPercentage( cMilitaryEscrowID, cAllResources, 0.0);
- kbEscrowAllocateCurrentResources();
-
- aiSetAutoGatherEscrowID(cRootEscrowID);
- aiSetAutoFarmEscrowID(cRootEscrowID);
- gathererTypeID = kbTechTreeGetUnitIDTypeByFunctionIndex(cUnitFunctionGatherer,0);
-
-
- int herdPlanID=aiPlanCreate("GatherHerdable Plan", cPlanHerd);
- if (herdPlanID >= 0)
- {
- aiPlanAddUnitType(herdPlanID, cUnitTypeHerdable, 0, 100, 100);
- aiPlanSetVariableInt(herdPlanID, cHerdPlanBuildingTypeID, 0, cUnitTypeSettlementLevel1);
- aiPlanSetActive(herdPlanID);
- }
-
- aiSetResourceGathererPercentageWeight(cRGPScript, 1);
- aiSetResourceGathererPercentageWeight(cRGPCost, 0);
-
- kbSetAICostWeight(cResourceFood, 1.0);
- kbSetAICostWeight(cResourceWood, 0.7);
- kbSetAICostWeight(cResourceGold, 0.8);
- kbSetAICostWeight(cResourceFavor, 7.0);
-
- aiSetResourceGathererPercentage(cResourceFood, 7.0/11.0, false, cRGPScript);
- aiSetResourceGathererPercentage(cResourceWood, 3.0/11.0, false, cRGPScript);
- aiSetResourceGathererPercentage(cResourceGold, 1.0/11.0, false, cRGPScript);
- aiSetResourceGathererPercentage(cResourceFavor, 0.0, false, cRGPScript);
- aiNormalizeResourceGathererPercentages(cRGPScript);
-
- //bool aiSetResourceBreakdown( int resourceTypeID, int resourceSubTypeID, int numberPlans, int planPriority, float percentage, int baseID )
- // aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeEasy, numFoodEasyPlans, 50, 1.0, gMainBaseID);
- // aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeHuntAggressive, numFoodHuntAggressivePlans, 100, 1.0, gMainBaseID);
- aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeFarm, 1, 50, 1.0, mainBase);
- aiSetResourceBreakdown(cResourceWood, cAIResourceSubTypeEasy, 1, 50, 1.0, woodBase);
- aiSetResourceBreakdown(cResourceGold, cAIResourceSubTypeEasy, 1, 50, 1.0, mainBase);
- // aiSetResourceBreakdown(cResourceFavor, cAIResourceSubTypeEasy, numFavorPlans, 50, 1.0, gMainBaseID);
-
- // Create villager maintain plan
- createSimpleMaintainPlan(gathererTypeID, 11, true, mainBase);
- }
-
-
-
-
- // Called by a trigger, to let AI know that it's time to start maintain plans, etc.
- void defend(int parm=-1)
- {
- // Init low-priority defend plan to manage hoplites
- int defendPlan =aiPlanCreate("Defend Plan", cPlanDefend);
- if (defendPlan >= 0)
- {
- aiPlanAddUnitType(defendPlan, cUnitTypeMilitary, 0, 200, 200); // All unassigned mil units
- aiPlanSetDesiredPriority(defendPlan, 10); // Way low, below scouting and attack
- aiPlanSetVariableVector(defendPlan, cDefendPlanDefendPoint, 0, kbGetBlockPosition(cbTownCenter));
- aiPlanSetVariableFloat(defendPlan, cDefendPlanEngageRange, 0, 60);
- aiPlanSetVariableBool(defendPlan, cDefendPlanPatrol, 0, false);
- aiPlanSetVariableFloat(defendPlan, cDefendPlanGatherDistance, 0, 20.0);
- aiPlanSetInitialPosition(defendPlan, kbGetBlockPosition(cbTownCenter));
- aiPlanSetUnitStance(defendPlan, cUnitStanceDefensive);
-
- aiPlanSetVariableInt(defendPlan, cDefendPlanRefreshFrequency, 0, 5);
- aiPlanSetNumberVariableValues(defendPlan, cDefendPlanAttackTypeID, 2, true);
- aiPlanSetVariableInt(defendPlan, cDefendPlanAttackTypeID, 0, cUnitTypeUnit);
- aiPlanSetVariableInt(defendPlan, cDefendPlanAttackTypeID, 1, cUnitTypeBuilding);
-
- aiPlanSetActive(defendPlan);
- aiEcho("Creating defend plan");
- }
- }
-
-
- // Called by a trigger
- void serpents(int parm=-1)
- {
- xsEnableRule("useSerpents");
- }
-
-
- void age2EventHandler(int bogus=-1)
- {
-
- }
-
- void age3EventHandler(int bogus=-1)
- {
-
- }
-
-
- void age4EventHandler(int bogus=-1)
- {
-
- }
-
-
-
-
-
-
- void attack(int player = -1)
- {
- int qty = -1;
- qty = getUnassignedUnitCount(kbGetBlockPosition(cbTownCenter), 50.0, cMyID, cUnitTypeMilitary);
- if (qty < 1)
- return;
-
- int attackID=aiPlanCreate("Attack "+timeString()+" ", cPlanAttack);
- if (attackID < 0)
- {
- return;
- }
-
- if (aiPlanSetVariableInt(attackID, cAttackPlanPlayerID, 0, player) == false)
- {
- return;
- }
-
- if (aiPlanSetNumberVariableValues(attackID, cAttackPlanTargetTypeID, 2, true) == false)
- {
- return;
- }
-
- // aiPlanSetVariableInt(attackID, cAttackPlanQueryID, 0, attackQuery);
-
- // add "unit" and "building" to attack list
- aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit);
- aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 1, cUnitTypeBuilding);
-
- if (aiRandInt(2) > 0)
- aiPlanSetVariableInt(attackID, cAttackPlanAttackRouteID, 0, routeInner);
- else
- aiPlanSetVariableInt(attackID, cAttackPlanAttackRouteID, 0, routeOuter);
-
- aiPlanSetVariableInt(attackID, cAttackPlanLastRefreshTime, 0, 30);
-
- aiPlanSetVariableVector(attackID, cAttackPlanGatherPoint, 0, kbGetBlockPosition(cbTownCenter));
- aiPlanSetVariableFloat(attackID, cAttackPlanGatherDistance, 0, 15.0);
-
- aiPlanAddUnitType(attackID, cUnitTypeMilitary, 0, qty, qty);
-
-
- aiPlanSetInitialPosition(attackID, kbGetBlockPosition(cbTownCenter));
- aiPlanSetRequiresAllNeedUnits(attackID, true);
- aiPlanSetActive(attackID);
- aiEcho("Activating attack plan "+attackID+" with "+qty+" units.");
- }
-
-
-
- void spawn(int parm = -1)
- {
- aiEcho("Spawn fired with parm "+parm);
- if (parm == 0)
- attack(1);
- if (parm == 1)
- attack(8);
- if (parm == 2)
- attack(1);
- }
-
-
-
-
-
-
- void main()
- {
- aiEcho("Starting Scn10p2.xs");
- kbSetTownLocation(kbGetBlockPosition(cbTownCenter));
-
- //Calculate some areas.
- kbAreaCalculate(1200.0);
-
- aiRandSetSeed();
-
- mainBase = initMainBase(kbGetBlockPosition(cbTownCenter), 60.0);
- woodBase = makeBase(kbGetBlockPosition(cbBase2), 20.0);
- initEcon();
-
- aiSetAgeEventHandler(cAge2, "age2EventHandler");
- aiSetAgeEventHandler(cAge3, "age3EventHandler");
- aiSetAgeEventHandler(cAge4, "age4EventHandler");
-
- routeInner = attackRoute("Inner Attack Route",cbRouteInnerA, cbRouteInnerB, cbRouteInnerC);
- routeOuter = attackRoute("Outer Attack Route",cbRouteOuterA, cbRouteOuterB, cbRouteOuterC);
-
- }
-
-
-
-
-
-
-
- // *****************************************************************************
- //
- // RULES
- //
- // *****************************************************************************
-
-
- rule goToAge3
- inactive
- mininterval 20
- {
- if ( (xsGetTime()/1000) < age3Time )
- return;
- researchTech(cTechAge3Nephthys);
- xsEnableRule("goToAge4");
- xsEnableRule("getAge3UnitUpgrades");
- xsEnableRule("getAge3ArmoryUpgrades");
- xsDisableSelf();
- }
-
- rule goToAge4
- inactive
- mininterval 20
- {
- if ( (xsGetTime()/1000) < age4Time )
- return;
- researchTech(cTechAge4Horus);
- xsEnableRule("getAge4UnitUpgrades");
- xsEnableRule("getAge4ArmoryUpgrades");
- xsDisableSelf();
- }
-
-
-
- rule getAge2UnitUpgrades
- inactive
- minInterval 20
- {
- if ( (xsGetTime()/1000) < (startTime + startTime + age3Time)/3 )
- return; // Wait till 1/3 to age3
- researchTech(cTechMediumAxemen);
- researchTech(cTechMediumSlingers);
- researchTech(cTechMediumSpearmen);
- xsDisableSelf();
- }
-
- rule getAge2ArmoryUpgrades
- inactive
- minInterval 20
- {
- if ( (xsGetTime()/1000) < (startTime + age3Time + age3Time)/3 )
- return; // Wait till 2/3 to age3
- aiEcho("Getting age 2 armory upgrades");
- researchTech(cTechCopperWeapons);
- researchTech(cTechCopperMail);
- researchTech(cTechCopperShields);
- xsDisableSelf();
- }
-
- rule getAge3UnitUpgrades
- inactive
- minInterval 20
- {
- if ( (xsGetTime()/1000) < (age3Time+300) )
- return;
- researchTech(cTechHeavyAxemen);
- researchTech(cTechHeavySlingers);
- researchTech(cTechHeavySpearmen);
- researchTech(cTechHeavyChariots);
- xsDisableSelf();
- }
-
- rule getAge3ArmoryUpgrades
- inactive
- minInterval 20
- {
- if ( (xsGetTime()/1000) < (age3Time+300) )
- return;
- researchTech(cTechBronzeWeapons);
- researchTech(cTechBronzeMail);
- researchTech(cTechBronzeShields);
- xsDisableSelf();
- }
-
- rule getAge4UnitUpgrades
- inactive
- minInterval 20
- {
- if ( (xsGetTime()/1000) < (age4Time+600) )
- return;
- researchTech(cTechChampionAxemen);
- researchTech(cTechChampionSlingers);
- researchTech(cTechChampionSpearmen);
- researchTech(cTechChampionChariots);
- xsDisableSelf();
- }
-
- rule getAge4ArmoryUpgrades
- inactive
- minInterval 20
- {
- if ( (xsGetTime()/1000) < (age4Time+300) )
- return;
- researchTech(cTechIronWeapons);
- researchTech(cTechIronMail);
- researchTech(cTechIronShields);
- xsDisableSelf();
- }
-
-
-
- rule scout
- inactive
- {
- // just set up an explore plan
- int exploreID = aiPlanCreate("Explore", cPlanExplore);
- if(exploreID >= 0)
- {
- //aiPlanAddVariableFloat( exploreID, cExplorePlanLOSMultiplier, "LOS Multiplier", 1);
- aiPlanSetVariableFloat( exploreID, cExplorePlanLOSMultiplier, 0, 4.0 );
- aiPlanAddUnitType(exploreID, cUnitTypeSpearman, 1, 1, 1);
- aiPlanSetActive(exploreID);
- }
- xsDisableSelf();
- }
-
-
- /* Sample
- rule attackGenerator
- minInterval 10
- active
- {
- //aiEcho("attack check running, next time is "+nextAttackTime);
- if ( (xsGetTime()/1000) < nextAttackTime )
- return;
-
- testAttack();
- nextAttackTime = (xsGetTime()/1000) + attackInterval;
- attackSize = attackSize + attackSizeIncrement;
- aiEcho("Next attack size will be "+attackSize+".");
- }
- */
-
-
-
- rule useVision // When it's time, cast vision at one of four markers.
- minInterval 5
- inactive
- {
- /*
-
-
- if (visionTime < 0)
- return;
-
- int rand = aiRandInt(4);
- switch (rand)
- {
- case 0:
- {
- aiCastGodPowerAtPosition(cTechVision, kbGetBlockPosition(cbVision0));
- break;
- }
- case 1:
- {
- aiCastGodPowerAtPosition(cTechVision, kbGetBlockPosition(cbVision1));
- break;
- }
- case 2:
- {
- aiCastGodPowerAtPosition(cTechVision, kbGetBlockPosition(cbVision2));
- break;
- }
- case 3:
- {
- aiCastGodPowerAtPosition(cTechVision, kbGetBlockPosition(cbVision3));
- break;
- }
- }
- aiEcho("Vision has been used");
- */
- xsDisableSelf();
- }
-
-
-
- rule useSerpents // Same logic as lightning, look for enemy military units
- minInterval 5
- inactive
- {
-
- // look for a group of 7 enemy units, at the Migdol location or at my main army's location
- int targetUnit = -1;
-
- static int tempQuery = -1;
- if (tempQuery < 0)
- { // Doesn't exist, set it up
- tempQuery = kbUnitQueryCreate("useSerpents1");
- if ( configQuery(tempQuery, cUnitTypeUnit, -1, cUnitStateAlive, 1, kbGetBlockPosition(cbTownCenter), true, 75) == false)
- return;
- }
- kbUnitQueryResetResults(tempQuery);
- int targetCount = kbUnitQueryExecute(tempQuery);
-
- if (targetCount < 7)
- {
- if (lastAttackPlanID < 0)
- return;
- vector pVec = aiPlanGetLocation(lastAttackPlanID);
- if (xsVectorGetX(pVec)>=0)
- {
- static int tempQuery2 = -1;
- if (tempQuery2 < 0)
- { // Doesn't exist, set it up
- tempQuery2 = kbUnitQueryCreate("useSerpents2");
- if ( configQuery(tempQuery2, cUnitTypeMilitary, -1, cUnitStateAlive, 1, pVec, true, 50) == false)
- return;
- }
- else
- kbUnitQuerySetPosition(tempQuery, pVec); // Because pVec changes as army moves
- kbUnitQueryResetResults(tempQuery2);
- targetCount = kbUnitQueryExecute(tempQuery2);
- if (targetCount < 7)
- return;
- else
- targetUnit = kbUnitQueryGetResult(tempQuery2, 0); // grab first unit
- }
- }
- else
- targetUnit = kbUnitQueryGetResult(tempQuery, targetCount/2); // grab middle unit
-
-
- aiEcho("Using Plague of Serpents at "+kbUnitGetPosition(targetUnit));
- if ( aiCastGodPowerAtPosition(cTechSerpents, kbUnitGetPosition(targetUnit)) == true)
- xsDisableSelf();
- else
- aiEcho("Serpents failed at "+kbUnitGetPosition(targetUnit));
- }
-
-
- rule useAncestors // Same logic as Serpents, look for enemy military units
- minInterval 5
- inactive
- {
-
- // look for a group of 7 enemy units, at the Migdol location or at my main army's location
- int targetUnit = -1;
-
- static int tempQuery = -1;
- if (tempQuery < 0)
- { // Doesn't exist, set it up
- tempQuery = kbUnitQueryCreate("useAncestors1");
- if ( configQuery(tempQuery, cUnitTypeUnit, -1, cUnitStateAlive, 1, kbGetBlockPosition(cbTownCenter), true, 75) == false)
- return;
- }
- kbUnitQueryResetResults(tempQuery);
- int targetCount = kbUnitQueryExecute(tempQuery);
-
- if (targetCount < 7)
- {
- vector pVec = aiPlanGetLocation(lastAttackPlanID);
- if (xsVectorGetX(pVec)>=0)
- {
- static int tempQuery2 = -1;
- if (tempQuery2 < 0)
- { // Doesn't exist, set it up
- tempQuery2 = kbUnitQueryCreate("useAncestors2");
- if ( configQuery(tempQuery, cUnitTypeMilitary, -1, cUnitStateAlive, 1, pVec, true, 50) == false)
- return;
- }
- kbUnitQueryResetResults(tempQuery2);
- targetCount = kbUnitQueryExecute(tempQuery2);
- if (targetCount < 7)
- return;
- else
- targetUnit = kbUnitQueryGetResult(tempQuery2, 0); // grab first unit
- }
- else
- return; // No army to check
- }
- else//SkeletonPower//PharaohRespawnCityoftheDead
- targetUnit = kbUnitQueryGetResult(tempQuery, targetCount/2); // grab middle unit
-
-
- aiEcho("Using Ancestors");
- if ( aiCastGodPowerAtPosition(cTechSkeletonPower, kbUnitGetPosition(targetUnit)) == true)
- xsDisableSelf();
- else
- aiEcho("Ancestors failed at "+kbUnitGetPosition(targetUnit));
-
- }
-
-
-
-